package by.dvrudenko.avtobaza.webapp.page.order;

import java.util.Arrays;
import java.util.Iterator;

import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import by.dvrudenko.avtobaza.datamodel.Route;
import by.dvrudenko.avtobaza.datamodel.UserOrder;
import by.dvrudenko.avtobaza.datamodel.UserOrder_;
import by.dvrudenko.avtobaza.datamodel.enums.OrderStatus;
import by.dvrudenko.avtobaza.datamodel.enums.UserRole;
import by.dvrudenko.avtobaza.services.CarService;
import by.dvrudenko.avtobaza.services.DriverService;
import by.dvrudenko.avtobaza.services.RouteService;
import by.dvrudenko.avtobaza.services.UserOrderService;
import by.dvrudenko.avtobaza.webapp.page.AbstractPanel;
import by.dvrudenko.avtobaza.webapp.page.car.panel.MyPagingNavigator;
import by.dvrudenko.avtobaza.webapp.page.createOrder.createOrderPage;
import by.dvrudenko.avtobaza.webapp.page.createRoute.CreateRoutePage;
import by.dvrudenko.avtobaza.webapp.page.route.page.RoutePage;
import by.dvrudenko.avtobaza.webapp.utils.renderer.OrderStatusChoiseRenderer;
import by.dvrudenko.avtobaza.webapp.utils.security.SecuredLinkForAdmin;
import by.dvrudenko.avtobaza.webapp.utils.security.SecuredLinkForAdminAjax;
import by.dvrudenko.avtobaza.webapp.utils.security.SecuredLinkForDriverAjax;
import by.dvrudenko.avtobaza.webapp.utils.security.SecuredLinkForUser;

public class OrderListPanel extends AbstractPanel {

	@Inject
	private UserOrderService userOrderService;
	
	@Inject
	private RouteService routeService;
	
	@Inject
	private CarService carService;
	
	@Inject 
	private DriverService driverService;
	
	private static final Logger LOGGER = LoggerFactory.getLogger(OrderListPanel.class);	

	public OrderListPanel(String id) {
		super(id);
		setOutputMarkupId(true);
		
		final Model<OrderStatus> selectedStatus = new Model<OrderStatus>();
			
		UserOrderDataProvider userOrderDataProvider = new UserOrderDataProvider();

		final WebMarkupContainer tableBody = new WebMarkupContainer("wrapper-body");

		add(tableBody);

		// таблица для вывода  заказов
		DataView<UserOrder> dataView = new DataView<UserOrder>("list", userOrderDataProvider, 5) {
			@Override
			protected void populateItem(final Item<UserOrder> item) {
				final UserOrder userOrder = item.getModelObject();				
	
				item.add(new Label("cargoBeginningCity.cityName"));				
				item.add(new Label("cargoFinalCity.cityName"));
				item.add(new Label("orderDate" ));				
				item.add(new Label("cargoWeight"));
				item.add(new Label("cargoVolume"));
				item.add(new Label("cargoDescription"));
				
				// комбик с статусами заказов
				final DropDownChoice<OrderStatus> dropDownOrderStatus =new DropDownChoice<OrderStatus>("orderStatus", /*selectedStatus,*/ 
						Arrays.asList(OrderStatus.values()), OrderStatusChoiseRenderer.INSTANCE);
				dropDownOrderStatus.setEnabled(false);
				dropDownOrderStatus.setOutputMarkupId(true);	
				
				// событие которое будет отрабатываться при изменении статуса заказа
				dropDownOrderStatus.add(new AjaxFormComponentUpdatingBehavior("change")
		        {
					@Override
					protected void onUpdate(AjaxRequestTarget target) {		
						userOrder.setOrderStatus(dropDownOrderStatus.getModelObject());
					}			
		        });
				item.add(dropDownOrderStatus);
				
				// ссылка для изменения статуса заказа
				final AjaxLink<Void> changeOrderStatus = new SecuredLinkForDriverAjax("changeOrderStatus") {
					@Override
					public void onClick(AjaxRequestTarget target) {
						if (dropDownOrderStatus.getModelObject().equals(OrderStatus.finish)){							
							info(new ResourceModel("p.home.createorder.cantEdit").getObject().toString());
							target.addChildren(getPage(), FeedbackPanel.class);
						}else if (dropDownOrderStatus.getModelObject().equals(OrderStatus.processed)){
							info(new ResourceModel("p.home.createorder.cantEditNotCar").getObject().toString());
							target.addChildren(getPage(), FeedbackPanel.class);											
						}else{							
							dropDownOrderStatus.setEnabled(true);
							target.add(dropDownOrderStatus);
						}
					}

				};
				item.add(changeOrderStatus);			
				item.add(new Label("anyDescription"));
				
				
				// ссылка для сохранения статуса заказа
				final AjaxLink<Void>saveOrderStatus = new SecuredLinkForDriverAjax("saveOrderStatus") {			
					@Override
					public void onClick(AjaxRequestTarget target) {
						dropDownOrderStatus.setEnabled(false);
						
						if (dropDownOrderStatus.getModelObject().equals(OrderStatus.finish)){
							routeService.changeRouteStatusByOrderId(userOrder.getId());
						}
						userOrderService.saveOrUpdate(userOrder);		
						LOGGER.info(user.getId() + " userId save order status");
						target.add(dropDownOrderStatus);
					}
					

				};	
				item.add(saveOrderStatus);
				
				/* ссылка, в зависимости от статуса заказа принимает разное значение
				 * Посмотреть машину
				 * Отправить машину
				 * Маршрут был удален
				 * 
				 */
				Link<Void> linkAction;		
				if (userOrder.getOrderStatus().equals(OrderStatus.pick_up_cargo) ||
						userOrder.getOrderStatus().equals(OrderStatus.rides_for_cargo)){
						linkAction = new SecuredLinkForUser("orderAction"){
						public void onClick() {
							setResponsePage(new RoutePage(routeService.getRouteByUserOrder(userOrder.getId())));
						};
					};
					linkAction.add(new Label("buttonValue", new ResourceModel("p.home.createorder.vewCar")));
					item.add(linkAction);
					/*
					 *если статус заказа в обработке (OrderStatus.processed) 
					 *тогда, добавить кнопку отправить машину
					 */
				} else if (userOrder.getOrderStatus().equals(OrderStatus.processed)){
					    linkAction = new SecuredLinkForAdmin("orderAction"){
						public void onClick() {
							setResponsePage(new CreateRoutePage(new Route(), userOrder));
						};
					};
					linkAction.add(new Label("buttonValue",new ResourceModel("p.home.createorder.createRoute")));
					item.add(linkAction);
					
				} else if (userOrder.getOrderStatus().equals(OrderStatus.finish)){
					/* 
					 * если в таблице машрутов (Route) больше нет ссылки на данный заказ
					 * значит он был удален и ссылку для просмотра машины показывать не надо
					 */
					if((routeService.getRouteByUserOrder(userOrder.getId())==null)){
						
						
						linkAction = new SecuredLinkForUser("orderAction"){
							public void onClick() {
					
							};
						};
						linkAction.add(new Label("buttonValue", new ResourceModel("p.home.createorder.routeDelete")));
						item.add(linkAction);							
					/*
					 *если в таблице машрутов (Route) есть заказы то показывать ссылку на просмотр маршрута  
					 */
					
					}else{
						linkAction = new SecuredLinkForUser("orderAction"){
						public void onClick() {
							setResponsePage(new RoutePage(routeService.getRouteByUserOrder(userOrder.getId())));
						};
					};
					linkAction.add(new Label("buttonValue", new ResourceModel("p.home.createorder.vewCar")));
					item.add(linkAction);
					};						
							
					} else {
					throw new IllegalArgumentException("invalid OrderStatus");
				}
				
				
				/*
				 * 
				 * если маршрут закончен, можно удлалить его из базы
				 * если маршрут не закончен, его можно отредактировать 
				 * */
				if (userOrder.getOrderStatus().equals(OrderStatus.finish)){	
					// ссылка на удаление маршрута
					AjaxLink editAjax = new SecuredLinkForAdminAjax("edit"){
						@Override
						public void onClick(AjaxRequestTarget target) {							
							LOGGER.info("delete Order, userLogin - :"+user.getLogin());
							userOrderService.delete(userOrder);
							info(new ResourceModel("p.home.createorder.OrderDelete").getObject().toString());
							target.addChildren(getPage(), FeedbackPanel.class);	
							target.add(OrderListPanel.this);
						}
						
					};
					editAjax.add(new Label("buttonEditValue", new ResourceModel("p.home.createorder.DeleteOrder")));
					item.add(editAjax);
				
				}else {
					// ссылка на редактирование маршрута
					Link<Void> edit = new SecuredLinkForAdmin("edit"){
						@Override
						public void onClick() {
							setResponsePage(new createOrderPage(userOrder));
						}
				};
					edit.add(new Label("buttonEditValue", new ResourceModel("p.home.order.panel.changeOrderStatus")));
					item.add(edit);
			}	
				
				
				

			}
		};
		

		tableBody.add(dataView);

		add(new MyPagingNavigator("paging", dataView));

		//add(new OrderByBorder<SingularAttribute<UserOrder, ?>>("sortByCargoFinalCity", UserOrder_.cargoFinalCity, userOrderDataProvider));
		add(new OrderByBorder<SingularAttribute<UserOrder, ?>>("sortByCargoBeginningCity", UserOrder_.cargoBeginningCity, userOrderDataProvider));
		add(new OrderByBorder<SingularAttribute<UserOrder, ?>>("sortByCargoWeight", UserOrder_.cargoWeight, userOrderDataProvider));
		add(new OrderByBorder<SingularAttribute<UserOrder, ?>>("sortByCargoVolume", UserOrder_.cargoVolume, userOrderDataProvider));
		add(new OrderByBorder<SingularAttribute<UserOrder, ?>>("sortByOrderStatus", UserOrder_.orderStatus, userOrderDataProvider));
		add(new OrderByBorder<SingularAttribute<UserOrder, ?>>("sortByOrderDate", UserOrder_.orderDate, userOrderDataProvider));
	}

	private class UserOrderDataProvider extends SortableDataProvider<UserOrder, SingularAttribute<UserOrder, ?>> {

		public UserOrderDataProvider() {
			super();
			setSort(UserOrder_.orderDate, SortOrder.ASCENDING);
		}

		@Override
		public Iterator<? extends UserOrder> iterator(long first, long count) {

			SingularAttribute<UserOrder, ?> sortParam = getSort().getProperty();
			SortOrder propertySortOrder = getSortState().getPropertySortOrder(sortParam);
			boolean ascending = SortOrder.ASCENDING.equals(propertySortOrder);
			
			if (user.getRole().equals(UserRole.USER)){
				return userOrderService.getAllUserOrder(sortParam, ascending, (int) first, (int) count, user.getId()).iterator();
			}
			return userOrderService.getAllUserOrder(sortParam, ascending, (int) first, (int) count, null).iterator();
		}

		@Override
		public long size() {
			if (user.getRole().equals(UserRole.USER)){
			return userOrderService.getCount(user.getId());
			}
			return userOrderService.getCount(null);
		}

		@Override
		public IModel<UserOrder> model(UserOrder userOrder) {
			return new CompoundPropertyModel<UserOrder>(userOrder);
		}
		
		
	}

}
